home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************
- * fltga.c: FBM Release 1.0 25-Feb-90 Ian MacPhedran
- *
- * Author Ian MacPhedran.
- * Permission is given to use any portion of this file, (including
- * its entirety) for whatever you wish. Howvever, please note that
- * it was written for Michael Mauldin's FBM Library, and conditions
- * therein are more restrictive.
- *
- * FBM is Copyright (C) 1989,1990 by Michael Mauldin. Permission
- * is granted to use this file in whole or in part for any purpose,
- * educational, recreational or commercial, provided that this
- * copyright notice is retained unchanged. This software is
- * available to all free of charge by anonymous FTP and in the
- * UUNET archives.
- *
- * CONTENTS
- * read_tga (image, rfile, mstr, mlen)
- * write_tga (image, wfile)
- *
- * HISTORY
- * 25-Jun-90 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
- * Package for Release 1.0
- *
- * 13-Mar-89 Ian J. MacPhedran
- * Add write_tga
- *
- * 07-Mar-89 Ian J. MacPhedran, University of Saskatchewan.
- * Created.
- *****************************************************************/
-
- #include <stdio.h>
- #include "fbm.h"
-
- #ifndef lint
- static char *fbmid =
- "$FBM fltga.c <1.0> 25-Jun-90 by Ian MacPhedran, source code available \
- free from MLM@CS.CMU.EDU and from UUNET archives$";
- #endif
-
- /* For convenience, the TGA header file is included herein. */
-
- /*
- * Header file for Targa file definitions.
- *
- * These definitions will allow a consistant interface to build Targa (.TGA)
- * image files.
- *
- * Created NOV-15-1988 IJMP
- *
- */
-
- /* File header definition */
-
- struct TGA_ImageHeader {
- unsigned char IDLength;/* Length of Identifier String */
- unsigned char CoMapType; /* 0 = NoMap */
- unsigned char ImgType; /* Image Type (1,2,3,9,10) */
- unsigned char Index_lo, Index_hi;
- /* Index of first colour map entry */
- unsigned char Length_lo, Length_hi;
- /* Length of colour map (number of entries) */
- unsigned char CoSize; /* Length of colour map entry */
- unsigned char X_org_lo, X_org_hi; /* X Origin of Image */
- unsigned char Y_org_lo, Y_org_hi; /* Y Origin of Image */
- unsigned char Width_lo, Width_hi; /* Width of Image */
- unsigned char Height_lo, Height_hi; /* Height of Image */
- unsigned char PixelSize; /* Pixel Size (8,16,24) */
- unsigned AttBits : 4; /* Number of Attribute Bits per pixel */
- unsigned Rsrvd : 1; /* Reserved bit */
- unsigned OrgBit : 1;
- /* Origin Bit (0=lower left, 1=upper left) */
- unsigned IntrLve : 2; /* Interleaving Flag */
- };
-
- char TGA_ImageIDField[256];
-
- /* Definitions for Image Types */
-
- #define TGA_MapRGBType 1
- #define TGA_RawRGBType 2
- #define TGA_RawMonoType 3
- #define TGA_MapEnCodeType 9
- #define TGA_RawEnCodeType 10
-
- /*
- * read_tga(image, rfile, mstr, mlen)
- * from tga2rast.c:
- * Version 1.0 - first released for public consumption, 21 Feb, 1989
- *
- */
-
- #define MAXCOLOURS 16384
-
- /* Define flags for mode - these indicate special conditions */
- #define GREYSC 0
- #define COLOUR 1
- #define MAPPED 2
- #define RLENCD 4
- #define INTERL 8
- #define FOURWY 16
-
- unsigned char ColourMap[MAXCOLOURS][3];
- int RLE_count=0,RLE_flag=0;
-
- read_tga(image, rfile, mstr, mlen)
- FBM *image;
- FILE *rfile;
- char *mstr;
- int mlen;
- {
- /* Define Identifiers */
- struct TGA_ImageHeader *tga;
- int i, j, l;
- unsigned int temp1, temp2, mode;
- unsigned char r, g, b;
- unsigned long k, baseline,linewidth;
- unsigned char *Red, *Grn, *Blu, *Redk, *Grnk, *Bluk;
-
- /* Input the Targa file header */
- if ((tga=(struct TGA_ImageHeader *)
- malloc(sizeof(struct TGA_ImageHeader))) == NULL)
- {
- fprintf(stderr,"Can't allocate TGA memory\n");
- exit(1);
- }
-
- if ((i = fread(tga,1,18,rfile)) != 18)
- {
- fprintf(stderr,"Read only %d bytes in header\n",i);
- exit(1);
- }
- switch (tga->ImgType)
- {
- case TGA_MapRGBType:
- case TGA_RawRGBType:
- case TGA_RawMonoType:
- case TGA_MapEnCodeType:
- case TGA_RawEnCodeType:
- break;
-
- default:
- fprintf(stderr,"Targa File Type %d",tga->ImgType);
- fprintf(stderr," not supported!\n");
- exit(1);
- }
-
- /* Create output image header */
- temp1 = tga->Height_lo; temp2 = tga->Height_hi;
- image->hdr.rows = temp1 + temp2 * 256;
- temp1 = tga->Width_lo; temp2 = tga->Width_hi;
- image->hdr.cols = temp1 + temp2 * 256;
- /* If this is odd number of bytes, add one */
- if ((image->hdr.cols & 1) != 0) image->hdr.cols++;
-
- /* If greyscale, use only one plane */
- if (tga->ImgType == TGA_RawMonoType)
- {
- image->hdr.planes = 1;
- mode = GREYSC;
- }
- else
- {
- image->hdr.planes = 3;
- mode = COLOUR;
- }
-
- /* Uses 8 bits, sort of - 16 bits/pixel is 5 bits per colour */
- image->hdr.bits = 8;
- image->hdr.physbits = 8;
- image->hdr.rowlen = image->hdr.cols;
- image->hdr.plnlen = image->hdr.rows * image->hdr.cols;
- /* Ignore colour map for this version. */
- image->hdr.clrlen = 0;
- image->hdr.aspect = 1.0;
- image->hdr.title[0] = '\0';
- image->hdr.credits[0] = '\0';
-
- /* Get the Image */
- alloc_fbm(image);
-
- /* Read ID String, if present */
- if (tga->IDLength != 0)
- fread(TGA_ImageIDField,1,tga->IDLength,rfile);
-
- /* If present, read the colour map information */
- if (tga->CoMapType != 0)
- {
- temp1 = tga->Index_lo + tga->Index_hi * 256;
- temp2 = tga->Length_lo + tga->Length_hi * 256;
- if ((temp1+temp2+1) >= MAXCOLOURS)
- {
- fprintf(stderr,"Too many colours %d\n",(temp1+temp2+1));
- exit(1);
- }
- for (i=temp1; i<(temp1+temp2); i++)
- get_map_entry(&ColourMap[i][0],&ColourMap[i][1],
- &ColourMap[i][2],tga->CoSize,mode);
- if ((tga->ImgType != TGA_RawRGBType) &&
- (tga->ImgType != TGA_RawMonoType) &&
- (tga->ImgType != TGA_RawEnCodeType))
- mode = mode | MAPPED;
- }
-
- /* Check Run Length Encoding */
- if ((tga->ImgType == TGA_MapEnCodeType) ||
- (tga->ImgType == TGA_RawEnCodeType))
- mode = mode | RLENCD;
-
- /* Check for interlacing of the Targa file */
- switch (tga->IntrLve)
- {
- case 2: /* Four way interlace */
- mode = mode | FOURWY;
- case 1: /* Two way interlace */
- mode = mode | INTERL;
- case 0: /* No interlace */
- break;
- default: /* Reserved - we'll let it pass */
- break;
- }
-
- /* Set up byte map for writing */
-
- Red = image->bm;
- if ((mode & COLOUR) != GREYSC)
- {
- Grn = Red + image->hdr.plnlen;
- Blu = Grn + image->hdr.plnlen;
- }
- /* Read the Targa file body and convert to image format */
- linewidth = tga->Width_lo + tga->Width_hi * 256;
- for (i=0; i< image->hdr.rows; i++)
- {
- /* No interlace */
- if ((mode & INTERL) == 0)
- {
- j = i;
- }
- /* Two way interlace */
- else if ((mode & FOURWY) != 0)
- {
- if (2*i < image->hdr.rows)
- j = 2*i;
- else
- {
- j = i - image->hdr.rows/2;
- j = 2*j + 1;
- }
- }
- /* Four way interlace */
- else
- {
- if (4*i < image->hdr.rows)
- j = 4*i;
- else if (2*i < image->hdr.rows)
- {
- j = i - image->hdr.rows/4;
- j = 4*j + 1;
- }
- else if (4*i < 3*image->hdr.rows)
- {
- j = i - image->hdr.rows/2;
- j = 4*j + 2;
- }
- else
- {
- j = i - image->hdr.rows/2 - image->hdr.rows/4;
- j = 4*j + 3;
- }
- }
- k = (image->hdr.rows - 1 - j) * image->hdr.cols;
- Redk = Red + k;
- if ((mode & COLOUR) != GREYSC)
- {
- Grnk = Grn + k; Bluk = Blu + k;
- }
- for (j=0; j<linewidth; j++)
- {
- get_pixel(&r,&g,&b,tga->PixelSize,mode);
- *Redk++=r;
- if ((mode & COLOUR) != GREYSC)
- {
- *Grnk++=g; *Bluk++=b;
- }
- }
- }
- free(tga);
- }
-
-
- get_map_entry(Red,Grn,Blu,Size,mode)
- unsigned char *Red,*Grn,*Blu;
- int Size,mode;
- {
- unsigned int j,k,l,m;
- unsigned char i,r,g,b;
-
- /* read appropriate number of bytes, break into rgb & put in map */
- switch (Size)
- {
- case 8: /* Grey Scale already, read and triplicate */
- fread(&i,1,1,stdin);
- r = i; g = i; b = i;
- break;
-
- case 16: /* 5 bits each of red green and blue */
- case 15: /* Watch for byte order */
- fread(&j,1,1,stdin);
- fread(&k,1,1,stdin);
- l = j + k*256;
- r = ((l >> 10) & 31) << 3;
- g = ((l >> 5) & 31) << 3;
- b = (l & 31) << 3;
- break;
-
- case 32: /* Read alpha byte & throw away */
- case 24: /* Eight bits each of red green and blue */
- fread(&i,1,1,stdin); b = i;
- fread(&i,1,1,stdin); g = i;
- fread(&i,1,1,stdin); r = i;
- if (Size == 32) fread(&i,1,1,stdin);
- break;
-
- default:
- fprintf(stderr,"Unknown Pixel Size\n"); exit(1);
- }
- *Red = r; *Grn = g; *Blu = b;
- }
-
- get_pixel(rRed,rGrn,rBlu,Size,mode)
- unsigned char *rRed,*rGrn,*rBlu;
- int Size,mode;
- {
- static unsigned char Red, Grn, Blu;
- unsigned char i,j,k;
- static unsigned int l;
-
- /* Check if run length encoded. */
- if ((mode & RLENCD) != 0)
- {
- if (RLE_count == 0) /* Have to restart run */
- {
- fread(&i,1,1,stdin);
- RLE_flag = (i & 0x80) >> 7;
- if (RLE_flag == 0)
- { /* Stream of unencoded pixels */
- RLE_count = i + 1;
- }
- else
- { /* Single pixel replicated */
- RLE_count = i - 127;
- }
- RLE_count--; /* Decrement count & get pixel */
- }
- else
- { /* Have already read count & (at least) first pixel */
- RLE_count--;
- if (RLE_flag != 0)
- { /* Replicated pixels */
- goto PixEncode;
- }
- }
- }
- /* Read appropriate number of bytes, break into RGB */
- switch(Size)
- {
- case 8: /* Grey Scale - read a byte and triplicate */
- fread(&i,1,1,stdin);
- Red = i; Grn = i; Blu = i; l = i;
- break;
-
- case 16: /* Five bits each of red green and blue */
- case 15: /* Watch byte order */
- fread(&j,1,1,stdin);
- fread(&k,1,1,stdin);
- l = j + k*256;
- Red = ((k & 0x7C) << 1);
- Grn = ((k & 0x03) << 6) + ((j & 0xE0) >> 2);
- Blu = ((j & 0x1F) << 3);
- break;
-
- case 32: /* Read alpha byte & throw away */
- case 24: /* Eight bits each of red green and blue */
- fread(&i,1,1,stdin); Blu = i;
- fread(&i,1,1,stdin); Grn = i;
- fread(&i,1,1,stdin); Red = i;
- if (Size == 32) fread(&i,1,1,stdin);
- l = 0;
- break;
-
- default:
- fprintf(stderr,"Unknown Pixel Size\n"); exit(1);
- }
-
- PixEncode:
- if ((mode & MAPPED) == MAPPED)
- {
- *rRed = ColourMap[l][0];
- *rGrn = ColourMap[l][1];
- *rBlu = ColourMap[l][2];
- }
- else
- {
- *rRed = Red;
- *rGrn = Grn;
- *rBlu = Blu;
- }
- }
-
- /*
- * write_tga(image, wfile)
- *
- */
- write_tga(image, wfile)
- FBM *image;
- FILE *wfile;
- {
- unsigned char *Red, *Grn, *Blu, *Redk, *Grnk, *Bluk;
- unsigned char *Redc, *Grnc, *Bluc, *Redck, *Grnck, *Bluck;
- struct TGA_ImageHeader *tga;
- unsigned char buffer[MAXCOLOURS];
- unsigned int mode;
- unsigned long index, index2;
- int i, j, k, l;
-
- if (image->hdr.cols > (MAXCOLOURS / 2))
- {
- fprintf(stderr,"Line too wide is %d, must be %d\n",
- image->hdr.cols, MAXCOLOURS/2);
- exit(1);
- }
-
- if ((image->hdr.planes != 1) && (image->hdr.planes != 3))
- {
- fprintf(stderr,"TGA files must 1 or 3 planes deep\n");
- exit(1);
- }
- if (image->hdr.planes == 1) mode = GREYSC;
- else mode = COLOUR;
-
- if ((tga=(struct TGA_ImageHeader *)
- malloc(sizeof(struct TGA_ImageHeader))) == NULL)
- {
- fprintf(stderr,"Can't allocate TGA memory\n");
- exit(1);
- }
- tga->IDLength = 0; /* Don't write ID into file */
- tga->CoMapType = 0; /* Use raw bytes, not mapped */
-
- tga->ImgType = TGA_RawRGBType;
- if ((mode & COLOUR) == GREYSC) tga->ImgType = TGA_RawMonoType;
-
- tga->Index_hi = 0; tga->Index_lo = 0; /* Colour Mapped stuff */
- tga->Length_hi = 0; tga->Length_lo = 0;
- tga->CoSize = 8;
-
- tga->X_org_lo = 0; tga->X_org_hi = 0; /* Origin at 0,0 */
- tga->Y_org_lo = 0; tga->Y_org_hi = 0;
-
- tga->Width_hi = (unsigned char)(image->hdr.cols / 256);
- tga->Width_lo = (unsigned char)(image->hdr.cols % 256);
- tga->Height_hi = (unsigned char)(image->hdr.rows / 256);
- tga->Height_lo = (unsigned char)(image->hdr.rows % 256);
-
- tga->PixelSize = 16;
- if ((mode & COLOUR) == GREYSC) tga->PixelSize = 8;
-
- /* All funny bits set to zero */
- tga->AttBits = 0; tga->Rsrvd = 0; tga->OrgBit = 0; tga->IntrLve = 0;
-
- fwrite(tga,1,18,wfile); /* Write out header */
-
- Red = image->bm;
- l = image->hdr.cols;
- if ((mode & COLOUR) == COLOUR)
- {
- l = l * 2;
- Grn = Red + image->hdr.plnlen;
- Blu = Grn + image->hdr.plnlen;
- }
-
- if (image->hdr.clrlen > 0)
- {
- mode = mode | MAPPED;
- Redc = image->cm;
- if ((mode & COLOUR) == COLOUR)
- {
- Grnc = Redc + image->hdr.clrlen/3;
- Bluc = Grnc + image->hdr.clrlen/3;
- }
- }
-
- Redk = Red + image->hdr.plnlen - image->hdr.cols;
- if ((mode & COLOUR) == COLOUR)
- {
- Grnk = Grn + image->hdr.plnlen - image->hdr.cols;
- Bluk = Blu + image->hdr.plnlen - image->hdr.cols;
- }
-
- /* Okay, ready to write */
- for (j=0; j<image->hdr.rows; j++)
- {
- for (i=0; i<image->hdr.cols; i++)
- {
- index = *Redk++;
- if ((mode & COLOUR) == COLOUR)
- index = (index << 16) + ((*Grnk++) << 8) + *Bluk++;
-
- if ((mode & MAPPED) == MAPPED)
- {
- index2 = index;
- Redck = Redc + index2;
- index = *Redck;
- if ((mode & COLOUR) == COLOUR)
- {
- Grnck = Grnc + index2; Bluck = Bluc + index2;
- index = (index << 16) +
- ((unsigned long)*Grnck << 8) +
- *Bluck;
- }
- }
-
- if ((mode & COLOUR) == COLOUR)
- {
- index2 = ((index & 0x00f80000) >> 9)
- + ((index & 0x0000f800) >> 6)
- + ((index & 0x000000f8) >> 3);
- k = 2 * i;
- buffer[k] = (unsigned char)(index2 % 256);
- k = k + 1;
- buffer[k] = (unsigned char)(index2 / 256);
- }
- else
- {
- buffer[i] = (unsigned char)index;
- }
- }
- fwrite(buffer,l,1,wfile);
- Redk = Redk - 2 * image->hdr.cols;
- if ((mode & COLOUR) == COLOUR)
- {
- Grnk = Grnk - 2 * image->hdr.cols;
- Bluk = Bluk - 2 * image->hdr.cols;
- }
- }
- free(tga);
- }
-